package com.warmheart.controller.main;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.warmheart.core.util.IpUtil;
import com.warmheart.entity.login.LoginLog;
import com.warmheart.service.login.ILoginLogService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.warmheart.base.annotation.Auth;
import com.warmheart.base.controller.BaseController;
import com.warmheart.base.entity.LoginUser;
import com.warmheart.base.entity.Operator;
import com.warmheart.base.session.SessionLocalUtils;
import com.warmheart.base.session.SessionManager;
import com.warmheart.core.enums.ResultCode;
import com.warmheart.core.result.CommonResult;
import com.warmheart.core.util.OperatorUtil;
import com.warmheart.core.util.ParamMapUtil;
import com.warmheart.core.util.PasswordUtil;
import com.warmheart.entity.user.UserLogin;
import com.warmheart.service.user.IUserLoginService;

@RestController
@RequestMapping("/main")
public class LoginController extends BaseController {

    @Autowired(required = false)
    private IUserLoginService userLoginService;

    @Autowired(required = false)
    private SessionManager sessionManager;

    @Autowired(required = false)
    private ILoginLogService loginLogService;


    /**
     * 登录验证
     * 
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @PutMapping("/login")
    public CommonResult<Map<String, Object>> login(HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        Map<String, Object> jsonMap = getJsonMap(request);
        // TODO 具体实现，比如运维端端使用登录名+密码登录
        // 运维端端使用登录名+密码登录伪代码
        String loginName = ParamMapUtil.getString(jsonMap, "loginName");

        // 登录名不可为空
        if (StringUtils.isBlank(loginName)) {
            return CommonResult.failed(ResultCode.PARAM_EMPTY, "用户名不可为空");
        }
        //创建登录对象实体类，用来记录登录日志
        LoginLog loginLog = new LoginLog();
        loginLog.setName(loginName);
        String ipAddress = IpUtil.getIpAddr(request);
        loginLog.setIpAddress(ipAddress);

        // 密码不可为空
        String password = ParamMapUtil.getString(jsonMap, "password");
        if (StringUtils.isBlank(password)) {
            //登录日志设置状态status：02和失败原因
            loginLog.setStatus("02");
            loginLog.setFailReason("密码为空");
            //保存日志到数据库
            OperatorUtil.addOper(loginLog);
            loginLogService.add(loginLog);
            return CommonResult.failed(ResultCode.PARAM_EMPTY, "密码不可为空");
        }

        // 判断登录用户是否合法
        UserLogin checkMember = new UserLogin();
        checkMember.setLoginName(loginName);
        checkMember.setClientType("01");
        checkMember.setLoginType("02");
        checkMember = userLoginService.selectOne(checkMember);

        // 用户不存在
        if (checkMember == null) {
            //登录日志设置状态status：02和失败原因
            loginLog.setStatus("02");
            loginLog.setFailReason("该用户不存在");
            //保存日志到数据库
            OperatorUtil.addOper(loginLog);
            loginLogService.add(loginLog);
            return CommonResult.failed(ResultCode.PARAM_INVALID, "用户名或者密码错误");
        }
        loginLog.setStatus("01");

        // 密码验证
        byte[] salt = checkMember.getSalt().getBytes();
        String currPwd = PasswordUtil.encrypt(checkMember.getLoginName(), password, salt);
        if (!currPwd.equals(checkMember.getPassWd())) {
            //登录日志设置状态status：02和失败原因
            loginLog.setStatus("02");
            loginLog.setFailReason("密码错误");
            //保存日志到数据库
            OperatorUtil.addOper(loginLog);
            loginLogService.add(loginLog);
            return CommonResult.failed(ResultCode.PARAM_INVALID, "用户名或者密码错误");
        }
        loginLog.setStatus("01");
        loginLog.setUserId(checkMember.getUserId());

        //保存日志到数据库
        OperatorUtil.addOper(loginLog);
        loginLogService.add(loginLog);

        // 保存登录信息
        LoginUser loginUser = new LoginUser();
        loginUser.setUserId(checkMember.getUserId());

        // 保存登录信息实体类
        Operator operator = new Operator();
        operator.setLoginUser(loginUser);

        // 保存登录信息
        String token = sessionManager.setOperator(operator);
        // 存入本服务器缓存中，用于提高访问速度
        SessionLocalUtils.setOperator(operator);
        Map<String, Object> resultMap = new HashMap<String, Object>();
        resultMap.put("token", token);
        //获取当前登录用户ID
//        System.out.println(SessionLocalUtils.getOperator().getLoginUser().getUserId());
        return CommonResult.success("登录成功", resultMap);
    }

    /**
     * 退出登录
     * 
     * @param request
     * @return
     * @throws Exception
     */
    @Auth(verifyLogin = true)
    @RequestMapping("/logout")
    public CommonResult<Map<String, Object>> logout(HttpServletRequest request, HttpServletResponse response)
            throws Exception {

        // 清除REDIS存储的用户数据
        String sessionId = sessionManager.getSessionIdByToken(request);
        sessionManager.del(sessionId);
        return CommonResult.success("退出登录");
    }

    /**
     * 退出登录
     * 
     * @param request
     * @return
     * @throws Exception
     */
    @Auth(verifyLogin = true)
    @RequestMapping("/modifyPwd")
    public CommonResult<Map<String, Object>> modifyPwd(HttpServletRequest request, HttpServletResponse response)
            throws Exception {
        Map<String, Object> jsonMap = getJsonMap(request);

        String oldPassWd = ParamMapUtil.getString(jsonMap, "oldPassWd");
        if (StringUtils.isBlank(oldPassWd)) {
            return CommonResult.failed(ResultCode.PARAM_EMPTY, "旧密码不可为空");
        }
        String passWd = ParamMapUtil.getString(jsonMap, "passWd");
        if (StringUtils.isBlank(passWd)) {
            return CommonResult.failed(ResultCode.PARAM_EMPTY, "新密码不可为空");
        }

        String reg = "(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,}";
        if (!Pattern.matches(reg, passWd)) {
            return CommonResult.failed(ResultCode.PARAM_INVALID, "新密码必须由8位以上的英文数字组成,且必须同时包含英文大小写和数字");
        }

        // 根据用户ID、客户端类型和登录类型查询用户登录信息
        UserLogin checkUserLogin = new UserLogin();
        checkUserLogin.setUserId(getCurrentUserId());
        checkUserLogin.setClientType("01");
        checkUserLogin.setLoginType("02");
        checkUserLogin = this.userLoginService.selectOne(checkUserLogin);

        byte[] salt = checkUserLogin.getSalt().getBytes();
        String oldPwdCheck = PasswordUtil.encrypt(checkUserLogin.getLoginName(), oldPassWd, salt);
        if (!oldPwdCheck.equals(checkUserLogin.getPassWd())) {
            return CommonResult.failed(ResultCode.PARAM_INVALID, "旧密码错误");
        }

        // 设置新密码
        String newPassword = PasswordUtil.encrypt(checkUserLogin.getLoginName(), passWd, salt);
        checkUserLogin.setPassWd(newPassword);

        try {
            OperatorUtil.updateOper(checkUserLogin);
            userLoginService.updateIncludeAll(checkUserLogin);
        } catch (Exception e) {
            return CommonResult.failed(ResultCode.ERROR_SERVER, "修改密码失败");
        }
        return CommonResult.success("修改密码成功");
    }
}
